﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;

namespace SoftballStats_BL
{
    public partial class PlayerGame
    {
#region Other Properties
        private Guid _ID;
        private Guid _GameID;
        private Guid _PlayerID;
        private short _Singles;
        private short _Doubles;
        private short _Triples;
        private short _AtBats;
        private short _Runs;
        private short _HomeRuns;
        private short _RunsBattedIn;
        private short _TotalBases;
        private string _Average;
        private string _OnBasePercentage;
        private string _Slugging;
        private string _OPS;
        private short _BattingOrder;
        private string _Position;
        private short _Walks;
        private short _Hits;
        private Guid _SeasonID;
        private short _ReachedOnError;

        public Guid ID
        {
            get
            {
                return _ID;
            }
            set
            {
                _ID = value;
            }
        }

        public Guid GameID
        {
            get
            {
                return _GameID;
            }
            set
            {
                _GameID = value;
            }
        }

        public Guid PlayerID
        {
            get
            {
                return _PlayerID;
            }
            set
            {
                _PlayerID = value;
            }
        }

        public short Singles
        {
            get
            {
                return _Singles;
            }
            set
            {
                _Singles = value;
            }
        }

        public short Doubles
        {
            get
            {
                return _Doubles;
            }
            set
            {
                _Doubles = value;
            }
        }

        public short Triples
        {
            get
            {
                return _Triples;
            }
            set
            {
                _Triples = value;
            }
        }

        public short AtBats
        {
            get
            {
                return _AtBats;
            }
            set
            {
                _AtBats = value;
            }
        }

        public short Runs
        {
            get
            {
                return _Runs;
            }
            set
            {
                _Runs = value;
            }
        }

        public short HomeRuns
        {
            get
            {
                return _HomeRuns;
            }
            set
            {
                _HomeRuns = value;
            }
        }

        public short RunsBattedIn
        {
            get
            {
                return _RunsBattedIn;
            }
            set
            {
                _RunsBattedIn = value;
            }
        }

        public short TotalBases
        {
            get
            {
                return _TotalBases;
            }
            set
            {
                _TotalBases = value;
            }
        }

        public string Average
        {
            get
            {
                return _Average;
            }
            set
            {
                _Average = value;
            }
        }

        public string OnBasePercentage
        {
            get
            {
                return _OnBasePercentage;
            }
            set
            {
                _OnBasePercentage = value;
            }
        }

        public string Slugging
        {
            get
            {
                return _Slugging;
            }
            set
            {
                _Slugging = value;
            }
        }

        public string OPS
        {
            get
            {
                return _OPS;
            }
            set
            {
                _OPS = value;
            }
        }

        public short BattingOrder
        {
            get
            {
                return _BattingOrder;
            }
            set
            {
                _BattingOrder = value;
            }
        }

        public string Position
        {
            get
            {
                return _Position;
            }
            set
            {
                _Position = value;
            }
        }

        public short Walks
        {
            get
            {
                return _Walks;
            }
            set
            {
                _Walks = value;
            }
        }

        public short Hits
        {
            get
            {
                return _Hits;
            }
            set
            {
                _Hits = value;
            }
        }

        public Guid SeasonID
        {
            get
            {
                return _SeasonID;
            }
            set
            {
                _SeasonID = value;
            }
        }

        public short ReachedOnError
        {
            get
            {
                return _ReachedOnError;
            }
            set
            {
                _ReachedOnError = value;
            }
        }
#endregion

#region Public Methods
        public static List<PlayerGame> GetPlayerGamesByGameID(Guid gameID)
        {
            List<SoftballStats_BL.PlayerGame> lstPlayerGames = new List<SoftballStats_BL.PlayerGame>();

            try
            {
                using (SqlConnection conn = new SqlConnection(Utility.GetConnectiongString()))
                {
                    SqlCommand cmd = new SqlCommand();
                    cmd.Connection = conn;
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = "spGetPlayerGamesByGameID";
                    cmd.Parameters.AddWithValue("@GameID", gameID);
                    conn.Open();
                    using (SqlDataReader dr = cmd.ExecuteReader())
                    {
                        while (dr.Read())
                        {
                            PlayerGame thisPlayerGame = new PlayerGame();
                            thisPlayerGame.ID = Guid.Parse(dr["ID"].ToString());
                            thisPlayerGame.PlayerID = Guid.Parse(dr["PlayerID"].ToString());
                            thisPlayerGame.Singles = short.Parse(dr["Singles"].ToString());
                            thisPlayerGame.Doubles = short.Parse(dr["Doubles"].ToString());
                            thisPlayerGame.Triples = short.Parse(dr["Triples"].ToString());
                            thisPlayerGame.AtBats = short.Parse(dr["AtBats"].ToString());
                            thisPlayerGame.Runs = short.Parse(dr["Runs"].ToString());
                            thisPlayerGame.HomeRuns = short.Parse(dr["HomeRuns"].ToString());
                            thisPlayerGame.RunsBattedIn = short.Parse(dr["RunsBattedIn"].ToString());
                            thisPlayerGame.TotalBases = (short)((1 * thisPlayerGame.Singles) + (2 * thisPlayerGame.Doubles) + (3 * thisPlayerGame.Triples) + (thisPlayerGame.HomeRuns));
                            thisPlayerGame.Walks = short.Parse(dr["Walks"].ToString());
                            thisPlayerGame.ReachedOnError = short.Parse(dr["ReachedOnError"].ToString());
                            thisPlayerGame.Hits = (short)(thisPlayerGame.Singles + thisPlayerGame.Doubles + thisPlayerGame.Triples + thisPlayerGame.HomeRuns);
                            thisPlayerGame.Average = CalculateAverage(thisPlayerGame.Hits, thisPlayerGame.AtBats);
                            thisPlayerGame.OnBasePercentage = CalculateOnBasePercentage((short)(thisPlayerGame.Hits + thisPlayerGame.ReachedOnError), thisPlayerGame.AtBats, thisPlayerGame.Walks);
                            thisPlayerGame.Slugging = CalculateSlugging(thisPlayerGame.TotalBases, thisPlayerGame.AtBats);
                            thisPlayerGame.OPS = CalculateOPS(thisPlayerGame.OnBasePercentage, thisPlayerGame.Slugging);
                            thisPlayerGame.BattingOrder = short.Parse(dr["BattingOrder"].ToString());
                            thisPlayerGame.Position = dr["Position"].ToString();
                            thisPlayerGame.SeasonID = Guid.Parse(dr["SeasonID"].ToString());
                            lstPlayerGames.Add(thisPlayerGame);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Failed to get PlayerGames", ex);
            }

            return lstPlayerGames;
        }


        public static List<SoftballStats_BL.PlayerGame> GetPlayerGamesByPlayerAndSeasonID(Guid playerID, string firstName, string lastName, Guid seasonID)
        {
            List<SoftballStats_BL.PlayerGame> lstPlayerGames = new List<SoftballStats_BL.PlayerGame>();

            try
            {
                using (SqlConnection conn = new SqlConnection(Utility.GetConnectiongString()))
                {
                    SqlCommand cmd = new SqlCommand();
                    cmd.Connection = conn;
                    cmd.CommandType = CommandType.StoredProcedure;
                    if (firstName == "" && lastName == "")
                    {
                        cmd.CommandText = "spGetPlayerGamesByPlayerIDAndSeasonID";
                        cmd.Parameters.AddWithValue("@PlayerID", playerID);
                    }
                    else
                    {
                        cmd.CommandText = "spGetPlayerGamesByPlayerNameAndSeasonID";
                        cmd.Parameters.AddWithValue("@FirstName", firstName);
                        cmd.Parameters.AddWithValue("@LastName", lastName);
                    }
                    cmd.Parameters.AddWithValue("@SeasonID", seasonID);
                    conn.Open();
                    using (SqlDataReader dr = cmd.ExecuteReader())
                    {
                        while (dr.Read())
                        {
                            PlayerGame thisPlayerGame = new PlayerGame();
                            thisPlayerGame.ID = Guid.Parse(dr["ID"].ToString());
                            thisPlayerGame.PlayerID = Guid.Parse(dr["PlayerID"].ToString());
                            thisPlayerGame.Singles = short.Parse(dr["Singles"].ToString());
                            thisPlayerGame.Doubles = short.Parse(dr["Doubles"].ToString());
                            thisPlayerGame.Triples = short.Parse(dr["Triples"].ToString());
                            thisPlayerGame.AtBats = short.Parse(dr["AtBats"].ToString());
                            thisPlayerGame.Runs = short.Parse(dr["Runs"].ToString());
                            thisPlayerGame.HomeRuns = short.Parse(dr["HomeRuns"].ToString());
                            thisPlayerGame.RunsBattedIn = short.Parse(dr["RunsBattedIn"].ToString());
                            thisPlayerGame.TotalBases = (short)((1 * thisPlayerGame.Singles) + (2 * thisPlayerGame.Doubles) + (3 * thisPlayerGame.Triples) + (thisPlayerGame.HomeRuns));
                            thisPlayerGame.Walks = short.Parse(dr["Walks"].ToString());
                            thisPlayerGame.ReachedOnError = short.Parse(dr["ReachedOnError"].ToString());
                            thisPlayerGame.Hits = (short)(thisPlayerGame.Singles + thisPlayerGame.Doubles + thisPlayerGame.Triples + thisPlayerGame.HomeRuns);
                            thisPlayerGame.Average = CalculateAverage(thisPlayerGame.Hits, thisPlayerGame.AtBats);
                            thisPlayerGame.OnBasePercentage = CalculateOnBasePercentage((short)(thisPlayerGame.Hits + thisPlayerGame.ReachedOnError), thisPlayerGame.AtBats, thisPlayerGame.Walks);
                            thisPlayerGame.Slugging = CalculateSlugging(thisPlayerGame.TotalBases, thisPlayerGame.AtBats);
                            thisPlayerGame.OPS = CalculateOPS(thisPlayerGame.OnBasePercentage, thisPlayerGame.Slugging);
                            thisPlayerGame.BattingOrder = short.Parse(dr["BattingOrder"].ToString());
                            thisPlayerGame.Position = dr["Position"].ToString();
                            thisPlayerGame.SeasonID = Guid.Parse(dr["SeasonID"].ToString());
                            lstPlayerGames.Add(thisPlayerGame);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Failed to get season stats", ex);
            }

            return lstPlayerGames;
        }

        public static SoftballStats_BL.PlayerGame GetPlayerSeasonStats(Guid playerID, string firstName, string lastName, Guid seasonID)
        {
            List<SoftballStats_BL.PlayerGame> lstPlayerGames = GetPlayerGamesByPlayerAndSeasonID(playerID, firstName, lastName, seasonID);
            SoftballStats_BL.PlayerGame playerSeasonStats = new SoftballStats_BL.PlayerGame();
            int singles, doubles, triples, atBats, runs, homeRuns, rbi, totalBases, walks, hits, reachedOnError;
            singles = 0;
            doubles = 0;
            triples = 0;
            atBats = 0;
            runs = 0;
            homeRuns = 0;
            rbi = 0;
            totalBases = 0;
            walks = 0;
            hits = 0;
            reachedOnError = 0;

            playerSeasonStats.PlayerID = playerID;
            playerSeasonStats.SeasonID = seasonID;

            for (int i = 0; i < lstPlayerGames.Count; i++)
            {
                singles += lstPlayerGames[i].Singles;
                doubles += lstPlayerGames[i].Doubles;
                triples += lstPlayerGames[i].Triples;
                atBats += lstPlayerGames[i].AtBats;
                runs += lstPlayerGames[i].Runs;
                homeRuns += lstPlayerGames[i].HomeRuns;
                rbi += lstPlayerGames[i].RunsBattedIn;
                totalBases += lstPlayerGames[i].TotalBases;
                walks += lstPlayerGames[i].Walks;
                reachedOnError += lstPlayerGames[i].ReachedOnError;
                hits += lstPlayerGames[i].Hits;
            }

            playerSeasonStats.Singles = short.Parse(singles.ToString());
            playerSeasonStats.Doubles = short.Parse(doubles.ToString());
            playerSeasonStats.Triples = short.Parse(triples.ToString());
            playerSeasonStats.AtBats = short.Parse(atBats.ToString());
            playerSeasonStats.Runs = short.Parse(runs.ToString());
            playerSeasonStats.HomeRuns = short.Parse(homeRuns.ToString());
            playerSeasonStats.RunsBattedIn = short.Parse(rbi.ToString());
            playerSeasonStats.TotalBases = short.Parse(totalBases.ToString());
            playerSeasonStats.Walks = short.Parse(walks.ToString());
            playerSeasonStats.ReachedOnError = short.Parse(reachedOnError.ToString());
            playerSeasonStats.Hits = short.Parse(hits.ToString());
            playerSeasonStats.Average = CalculateAverage(playerSeasonStats.Hits, playerSeasonStats.AtBats);
            playerSeasonStats.OnBasePercentage = CalculateOnBasePercentage((short)(playerSeasonStats.Hits + playerSeasonStats.ReachedOnError), playerSeasonStats.AtBats, playerSeasonStats.Walks);
            playerSeasonStats.Slugging = CalculateSlugging(playerSeasonStats.TotalBases, playerSeasonStats.AtBats);
            playerSeasonStats.OPS = CalculateOPS(playerSeasonStats.OnBasePercentage, playerSeasonStats.Slugging);

            return playerSeasonStats;
        }

        private static string CalculateOPS(string onBasePercentage, string slugging)
        {
            double OBP = double.Parse(onBasePercentage);
            double SLG = double.Parse(slugging);
            return String.Format("{0:n3}", (OBP + SLG));
        }

        private static string CalculateSlugging(short totalBases, short atBats)
        {
            double totalBasesD = double.Parse(totalBases.ToString());
            double atBatsD = double.Parse(atBats.ToString());
            return String.Format("{0:n3}", (totalBasesD / atBatsD));
        }

        private static string CalculateOnBasePercentage(short hits, short atBats, short walks)
        {
            double topHalf = (double)(hits + walks);
            double bottomHalf = (double)(atBats + walks);
            return String.Format("{0:n3}", (topHalf / bottomHalf));
        }

        private static string CalculateAverage(short hits, short atBats)
        {
            double hitsD = double.Parse(hits.ToString());
            double atBatsD = double.Parse(atBats.ToString());
            return String.Format("{0:n3}", (hitsD / atBatsD));
        }
#endregion
    }
}
